-- Lua Battle System - 技能基类

local Logger = require("utils.logger")
local BattleConfig = require("config.battle_config")

local Skill = {
    -- 技能基本信息
    id = "",
    name = "",
    description = "",
    type = "physical", -- physical, magic, support
    
    -- 技能消耗
    cost = {
        mp = 0,
        hp = 0,
        items = {},
        cooldown = 0
    },
    
    -- 技能范围和目标
    range = "single", -- single, multiple, all, self
    target_type = "enemy", -- enemy, ally, any, self
    max_targets = 1,
    
    -- 技能释放条件
    release_conditions = {
        status_effects = {}, -- 需要的状态效果
        required_health = 0, -- 最低生命值要求
        required_mp = 0, -- 最低魔法值要求
        terrain = {}, -- 允许的地形
        weather = {}, -- 允许的天气
        custom_conditions = {} -- 自定义条件函数
    },
    
    -- 技能效果
    damage = {
        base = 0,
        multiplier = 1.0,
        variance = 0.1
    },
    healing = {
        base = 0,
        multiplier = 1.0,
        variance = 0.1
    },
    
    -- 状态效果
    status_effects = {
        target = {}, -- 对目标施加的状态效果
        caster = {} -- 对施法者施加的状态效果
    },
    
    -- 技能属性
    cooldown = 0,
    current_cooldown = 0,
    cast_time = 0,
    is_instant = false,
    
    -- 技能充能属性
    chargeable = false, -- 是否可充能
    max_charges = 1, -- 最大充能数
    current_charges = 1, -- 当前充能数
    charge_time = 0, -- 充能时间（回合数）
    current_charge_time = 0, -- 当前充能进度
    
    -- 技能特殊属性
    is_aoe = false,
    is_channeled = false,
    interruptible = true,
    
    -- 技能效果参数
    effects = {
        penetration = 0,
        crit_chance = 0,
        crit_multiplier = 0,
        accuracy = 1.0
    }
}

-- 技能构造函数
function Skill:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

-- 初始化技能
function Skill:init()
    self.current_cooldown = 0
    self.current_charges = self.max_charges
    self.current_charge_time = 0
    Logger.debug("技能初始化完成: " .. self.name)
end

-- 检查技能是否可用
function Skill:is_usable(caster, battle_state)
    -- 检查冷却时间或充能情况
    if self.chargeable then
        -- 可充能技能检查充能数
        if self.current_charges <= 0 then
            Logger.warn(self.name .. " 充能不足，当前充能: " .. self.current_charges)
            return false
        end
    else
        -- 普通技能检查冷却时间
        if self.current_cooldown > 0 then
            Logger.warn(self.name .. " 冷却中，剩余回合: " .. self.current_cooldown)
            return false
        end
    end
    
    -- 检查释放条件
    local conditions = self.release_conditions
    
    -- 检查状态效果要求
    for _, required_effect in ipairs(conditions.status_effects) do
        local has_effect = false
        for effect_id, effect in pairs(caster.status_effects) do
            if effect_id == required_effect then
                has_effect = true
                break
            end
        end
        if not has_effect then
            Logger.warn(caster.name .. " 缺少必要的状态效果: " .. required_effect)
            return false
        end
    end
    
    -- 检查最低生命值要求
    if conditions.required_health > 0 then
        local health_percentage = caster.hp / caster.max_hp
        if health_percentage < conditions.required_health then
            Logger.warn(caster.name .. " 生命值不足，当前: " .. math.floor(health_percentage * 100) .. "%，需要: " .. math.floor(conditions.required_health * 100) .. "%")
            return false
        end
    end
    
    -- 检查最低魔法值要求
    if conditions.required_mp > 0 then
        local mp_percentage = caster.mp / caster.max_mp
        if mp_percentage < conditions.required_mp then
            Logger.warn(caster.name .. " 魔法值不足，当前: " .. math.floor(mp_percentage * 100) .. "%，需要: " .. math.floor(conditions.required_mp * 100) .. "%")
            return false
        end
    end
    
    -- 检查地形要求
    if battle_state and #conditions.terrain > 0 then
        local terrain = battle_state.current_terrain or "normal"
        local is_valid_terrain = false
        for _, valid_terrain in ipairs(conditions.terrain) do
            if terrain == valid_terrain then
                is_valid_terrain = true
                break
            end
        end
        if not is_valid_terrain then
            Logger.warn(self.name .. " 无法在当前地形使用: " .. terrain)
            return false
        end
    end
    
    -- 检查天气要求
    if battle_state and #conditions.weather > 0 then
        local weather = battle_state.current_weather or "clear"
        local is_valid_weather = false
        for _, valid_weather in ipairs(conditions.weather) do
            if weather == valid_weather then
                is_valid_weather = true
                break
            end
        end
        if not is_valid_weather then
            Logger.warn(self.name .. " 无法在当前天气使用: " .. weather)
            return false
        end
    end
    
    -- 检查自定义条件
    for _, condition_func in ipairs(conditions.custom_conditions) do
        if type(condition_func) == "function" then
            local success, result = pcall(condition_func, caster, self, battle_state)
            if not success or not result then
                Logger.warn(self.name .. " 自定义条件不满足")
                return false
            end
        end
    end
    
    -- 检查MP消耗
    if self.cost.mp > 0 and caster.mp < self.cost.mp then
        Logger.warn(caster.name .. " MP不足，当前MP: " .. caster.mp .. "，需要: " .. self.cost.mp)
        return false
    end
    
    -- 检查HP消耗
    if self.cost.hp and self.cost.hp > 0 and caster.hp < self.cost.hp then
        Logger.warn(caster.name .. " HP不足，当前HP: " .. caster.hp .. "，需要: " .. self.cost.hp)
        return false
    end
    
    -- 检查物品消耗
    if self.cost.items then
        for _, item_cost in ipairs(self.cost.items) do
            if not caster.items[item_cost.id] or caster.items[item_cost.id] < item_cost.quantity then
                Logger.warn(caster.name .. " 物品不足: " .. item_cost.id)
                return false
            end
        end
    end
    
    return true
end

-- 消耗技能资源
function Skill:consume_resources(caster)
    -- 消耗MP
    if self.cost.mp and self.cost.mp > 0 then
        caster:consume_mp(self.cost.mp)
    end

    -- 消耗HP
    if self.cost.hp and self.cost.hp > 0 then
        caster.hp = caster.hp - self.cost.hp
        Logger.info(caster.name .. " 消耗了 " .. self.cost.hp .. " 点HP")
    end
    
    -- 消耗物品
    if self.cost.items then
        for _, item_cost in ipairs(self.cost.items) do
            caster.items[item_cost.id] = caster.items[item_cost.id] - item_cost.quantity
            if caster.items[item_cost.id] <= 0 then
                caster.items[item_cost.id] = nil
            end
            Logger.info(caster.name .. " 消耗了 " .. item_cost.quantity .. " 个 " .. item_cost.id)
        end
    end
end

-- 计算伤害
function Skill:calculate_damage(caster, target)
    local damage = 0
    
    if self.type == "physical" then
        damage = self.damage.base + caster.attack * self.damage.multiplier
    elseif self.type == "magic" then
        damage = self.damage.base + caster.magic_attack * self.damage.multiplier
    end
    
    -- 添加伤害浮动
    if self.damage.variance then
        local variance = damage * self.damage.variance
        damage = damage + math.random(-variance, variance)
    end
    
    -- 应用穿透效果
    if self.effects and self.effects.penetration and self.effects.penetration > 0 then
        if self.type == "physical" then
            damage = damage + target.defense * self.effects.penetration
        elseif self.type == "magic" then
            damage = damage + target.magic_defense * self.effects.penetration
        end
    end
    
    -- 确保伤害至少为1
    damage = math.max(1, damage)
    
    return damage
end

-- 计算治疗量
function Skill:calculate_healing(caster, target)
    local healing = 0
    
    if self.type == "support" then
        healing = self.healing.base + caster.magic_attack * self.healing.multiplier
    end
    
    -- 添加治疗浮动
    if self.healing.variance then
        local variance = healing * self.healing.variance
        healing = healing + math.random(-variance, variance)
    end
    
    -- 确保治疗至少为1
    healing = math.max(1, healing)
    
    return healing
end

-- 检查是否暴击
function Skill:is_critical(caster)
    local crit_chance = BattleConfig.damage_calculation.critical_chance + self.effects.crit_chance
    return math.random() < crit_chance
end

-- 应用技能效果
function Skill:apply_effects(caster, target, damage, healing, is_critical)
    local result = {
        damage = damage,
        healing = healing,
        is_critical = is_critical,
        status_effects_applied = {}
    }
    
    -- 对目标造成伤害
    if damage > 0 then
        local final_damage = target:take_damage(damage)
        result.damage = final_damage
    end
    
    -- 对目标进行治疗
    if healing > 0 then
        local final_healing = target:heal(healing)
        result.healing = final_healing
    end
    
    -- 应用状态效果到目标
    for _, effect_info in ipairs(self.status_effects.target) do
        local StatusEffects = require("characters.status_effects")
        local effect = StatusEffects.create_effect(effect_info.id, effect_info.params)
        if effect then
            target:add_status_effect(effect)
            table.insert(result.status_effects_applied, {
                target = target.id,
                effect = effect.id
            })
        end
    end
    
    -- 应用状态效果到施法者
    for _, effect_info in ipairs(self.status_effects.caster) do
        local StatusEffects = require("characters.status_effects")
        local effect = StatusEffects.create_effect(effect_info.id, effect_info.params)
        if effect then
            caster:add_status_effect(effect)
            table.insert(result.status_effects_applied, {
                target = caster.id,
                effect = effect.id
            })
        end
    end
    
    return result
end

-- 执行技能
function Skill:execute(caster, target, battle_state)
    -- 检查技能是否可用
    if not self:is_usable(caster, battle_state) then
        return nil
    end
    
    Logger.info(caster.name .. " 使用了 " .. self.name)
    
    -- 消耗资源
    self:consume_resources(caster)
    
    -- 处理冷却或充能
    if self.chargeable then
        -- 消耗充能
        self.current_charges = self.current_charges - 1
        Logger.debug(self.name .. " 消耗了1点充能，剩余充能: " .. self.current_charges)
    else
        -- 设置冷却时间
        self.current_cooldown = self.cooldown
    end
    
    -- 计算伤害和治疗
    local damage = self:calculate_damage(caster, target)
    local healing = self:calculate_healing(caster, target)
    
    -- 检查是否暴击
    local is_critical = self:is_critical(caster)
    if is_critical then
        damage = damage * (BattleConfig.damage_calculation.critical_multiplier + self.effects.crit_multiplier)
        Logger.info(self.name .. " 暴击了！")
    end
    
    -- 应用技能效果
    local result = self:apply_effects(caster, target, damage, healing, is_critical)
    
    Logger.debug("技能 " .. self.name .. " 执行结果: " .. 
        "伤害: " .. result.damage .. ", " ..
        "治疗: " .. result.healing .. ", " ..
        "暴击: " .. (is_critical and "是" or "否"))
    
    return result
end

-- 更新技能冷却和充能
function Skill:update_cooldown()
    if self.chargeable then
        -- 处理充能技能
        if self.current_charges < self.max_charges then
            -- 增加充能进度
            self.current_charge_time = self.current_charge_time + 1
            Logger.debug(self.name .. " 充能中，进度: " .. self.current_charge_time .. "/" .. self.charge_time)
            
            -- 检查是否完成充能
            if self.current_charge_time >= self.charge_time then
                -- 增加充能数
                self.current_charges = self.current_charges + 1
                self.current_charge_time = 0
                Logger.debug(self.name .. " 充能完成，当前充能: " .. self.current_charges .. "/" .. self.max_charges)
            end
        end
    else
        -- 处理普通技能冷却
        if self.current_cooldown > 0 then
            self.current_cooldown = self.current_cooldown - 1
            Logger.debug(self.name .. " 冷却减少，剩余回合: " .. self.current_cooldown)
        end
    end
end

-- 重置技能冷却和充能
function Skill:reset_cooldown()
    if self.chargeable then
        -- 重置充能
        self.current_charges = self.max_charges
        self.current_charge_time = 0
        Logger.debug(self.name .. " 充能重置，当前充能: " .. self.current_charges .. "/" .. self.max_charges)
    else
        -- 重置冷却
        self.current_cooldown = 0
        Logger.debug(self.name .. " 冷却重置")
    end
end

-- 获取技能状态
function Skill:get_state()
    local state = {
        id = self.id,
        name = self.name,
        current_cooldown = self.current_cooldown,
        cooldown = self.cooldown
    }
    
    -- 添加充能状态信息
    if self.chargeable then
        state.chargeable = true
        state.current_charges = self.current_charges
        state.max_charges = self.max_charges
        state.charge_time = self.charge_time
        state.current_charge_time = self.current_charge_time
    end
    
    return state
end

-- 导出模块
return Skill